/** @format */

import { logFn, recordErrorLog } from '../../utils'
import { resultsModel } from '../../sdk'
import { CODE_TYPES } from '../../constants'
import { doHandler } from '../../utils/'
import { CommonUserService, CommonBaseService } from '../../service/common'

type Constructor = new (...args: any[]) => {}

async function formatBaseInfos(context: IContext<IParams>, baseInfos: ICheckControllerInfos) {
  // 如果未调用registeInfos 则 重新注入userInfo和 activityInfo
  if (!baseInfos.registed) {
    if (!baseInfos.activityInfo && !baseInfos.noCheckActivity) {
      const baseService = new CommonBaseService(context)
      // 活动基本情况
      const activityInfo = await baseService.getBaseInfo(context.data.activityId)
      // const extraInfo = await baseService.getExtraInfo(activityInfo.isNike)
      if (!activityInfo && !baseInfos.noCheckActivity) return CODE_TYPES.ERROR_NO_ACTIVITY
      baseInfos.activityInfo = activityInfo
    }

    // 默认注入活动和用户信息并校验
    if (!baseInfos.userInfo) {
      // const userService = new CommonUserService(context)
      // const userInfo = await userService.getUserInfo()
      // if (!userInfo && !baseInfos.noCheckUser) return CODE_TYPES.ERROR_NO_USER
      // baseInfos.userInfo = userInfo
    }
  }
  return baseInfos
}

// 注入服务
export default function services(services: Constructor[] = []) {
  return (target: Object, name: string, descriptor: PropertyDescriptor) => {
    const method = descriptor.value

    descriptor.value = async function (...args: any[]) {
      let [context, otherArgs = {}, originServices = [], preCheckData = {}] = args
      const servicesInstance = services.map(v => new v(context))

      logFn(context)

      const baseInfos = await formatBaseInfos(context, otherArgs)

      if ((baseInfos as ICodeType).code) return resultsModel.error(baseInfos as ICodeType)

      // 默认全局try catch  如果有noCatch参数则直接执行
      // @ts-ignore
      if (baseInfos.noCatch) {
        // @ts-ignore
        delete baseInfos.noCatch
        return method.apply(target, [context, baseInfos, servicesInstance])
      }

      return await doHandler(target, method, [
        context,
        baseInfos,
        [...originServices, ...servicesInstance],
        preCheckData
      ])
    }
  }
}
